Funktionen

Eine Subroutine ist ein Unterprogramm (eine Prozedur), das mehrere zusammengehörende Anweisungen ausführt, ohne einen bestimmten Wert zurückzugeben. Eine vordefinierte Subroutine ist zum Beispiel die folgende Methode der Objekthierarchie von MS Excel:

Worksheets(“XY”).Columns(“A:C”).Calculate

Die vordefinierte Subroutine Calculate berechnet alle Formeln des Zellbereichs A:C des Tabellenblatts XY neu. Die folgende Subroutine ist hingegen benutzerdefiniert. zeigeBereichRot() zeigt den mit “XY” benannten Zellbereich rot an:

Sub zeigeBereichRot()
  Range(“XY").Select
  Selection.Font.ColorIndex = 3     ‘Farbindex = 3 (rot)
End Sub

Eine Funktion gibt im Gegensatz zur Subroutine einen Wert eines bestimmten Datentyps zurück. Die vordefinierte Tabellenblatt-Funktion SUMME(3;2) ergibt zum Beispiel den numerischen Wert 5. Eine Funktion kann deshalb in einer Formel (insbesondere einer Tabellenformel) vorkommen. Das Ergebnis der folgenden Formel ist zum Beispiel 10:

SUMME(3;2) + 5.

Wir haben im Beispiel QuadratDialog Anweisungen (insbesondere Steueranweisungen), Unterprogramme (Subroutinen und Funktionen), Datentypen und Objekte eingeführt. Die nächsten Abschnitte veranschaulichen diese Begriffe am Programm Wort.xls. Es löscht Wort für Wort einer Textzeile, bis sie leer ist. Das folgende Bild veranschaulicht den Programmablauf am Beispiel der Textzeile “Oh Klotilde, Du allein sollst und musst die Meine sein”:

Wort.xls.  gibt den Text auf dem Tabellenblatt “Ausgabeblatt” aus. Jede Zelle des Tabellenblatts beginnt auf dem Schnittpunkt einer Zeile und einer Spalte. Sie lässt sich deshalb mit der Eigenschaft Cells(Zeile, Spalte) eindeutig adressieren. Die Zeilen eines Tabellenblatts sind von oben bis unten nummeriert. Analog werden die Spalten von links nach rechts gezählt. Die erste Zeile des Texts steht deshalb in der Zelle (2, 2), die nächste in (3, 2) und die letzte in (11, 2).

Das Hilfethema Modularisierung zeigt, dass ein Problem nach dem Grundsatz “Divide et impera” in Teilprobleme (Module) zerlegt werden kann. Wir gehen auch in Wort.xls so vor. Der folgende Programmausschnitt zeigt die Hauptprozedur WortFürWortLöschen(). Im Initialisierungsteil weist sie zuerst den Text “Oh Klotilde ...” der Zelle am Schnittpunkt zwischen der zweiten Spalte und der zweiten Zeile des Ausgabeblatts zu. Dann löscht sie in einer Schleife solange das erste Wort der jeweiligen Zeile, bis der Text leer ist.

Sub WortFürWortLöschen()
  Dim Zeile As Integer, Text As String

  ‘ —- Initialisierung
  Zeile = 2
  Text = “Oh Klotilde, Du allein sollst und musst ...”
  ‘ —- Zeile 2
  Ausgabeblatt.Cells(Zeile, 2) = Text
  Do While einWortWeniger(Text)
    Zeile = Zeile + 1
    ‘ —- Zeile 3 etc.
    Ausgabeblatt.Cells(Zeile, 2) = Text
  Loop
End Sub

Das Löschen eines Worts und die Prüfung auf das Ende der Schleife delegiert die Subroutine an die Funktion einWortWeniger(Text):

Do While einWortWeniger(Text)
  Zeile = Zeile + 1.
  Ausgabeblatt.Cells(Zeile, 2) = Text
Loop

Ausführungsbedingung der While-Schleife ist die Funktion einWortWeniger(Text). Die Bedingung trifft solange zu, wie es möglich ist, auf jeder neuen Zeile ein Wort weniger anzuzeigen. Weil eine Bedingung immer wahr oder falsch ist, muss die Funktion den Wert True oder False ergeben. Die Funktion ist deshalb vom Datentyp Boolean (siehe Datentypen). Die Schleife erhöht in jedem Durchlauf die Nummer der jeweiligen Zelle und weist ihr den in der Funktion einWortWeniger(Text) gekürzten Text zu.

Der Aufruf von einWortWeniger(Text) übergibt das Argument Text. Das Hilfethema Argumente handelt nur von Argumenten, die vom aufgerufenen Unterprogramm nicht geändert werden. Text ist hingegen ein Eingabe- und Ausgabeargument. Es wird von der Funktion einWortWeniger(Text) modifiziert - nämlich ein Wort kürzer - zurückgegeben. Wir werden dieses Problem später vertiefen.

Die Subroutine WortFürWortLöschen() verwendet zwei Arten von Funktionen: 

Funktionsname und -argumente

Rückgabewert

InStr(Text, String)

Position von String in Text

Right(Text, N)

N rechte Zeichen von Text

Len(Text)

Zeichenzahl (engl. length) von Text

Die Definition von einWortWeniger folgt der allgemeinen Funktionssyntax:

Function <Name> ( <Argumente> ) As <Rückgabetyp>
    <Vereinbarungsanweisungen>
    <ausführbare Anweisungen>
End Function

Function einWortWeniger(Text As String) As Boolean
  Dim PosLeer As Integer

  PosLeer = InStr(Text, “ ”)
  If PosLeer <> 0 Then
    Text = Right(Text, Len(Text) - PosLeer)
    einWortWeniger = True
  Else
    einWortWeniger = False
  End If
End Function

Weil einWortWeniger(Text) den Text ohne das erste Wort zurückgeben soll, sucht es zuerst die Position der ersten Leerstelle des Texts (PosLeer). Falls eine Leerstelle existiert, weist die Funktion dem Argument Text den bisherigen Text ohne die Zeichen bis und mit der ersten Leerstelle zu. einWortWeniger wird False, falls keine Leerstelle mehr existiert, die den Text in einen linken und rechten Teil trennt.

Argumentübergabe

Jeder Aufruf von einWortWeniger(Text) ergibt nicht nur einen Rückgabewert True oder False, sondern ändert auch das Argument Text (“Oh Klotilde ...”). Eine aufrufende Prozedur kann der aufgerufenen Prozedur ein Argument als Adresse oder als Kopie übergeben:

Das übergebene Argument steht im Speicher des aufrufenden Programms. Wenn das aufgerufende Programm dieses Argument ändert, modifiziert es also einen Speicherplatz des aufrufenden Programms. Die Funktion einWortWeniger(Text) ändert zum Beispiel direkt den Text der Subroutine WortFürWortLöschen(), das heisst jeder Aufruf löscht unwiderruflich ein Wort des Originaltexts. Die Ausgabe von WortFürWortLöschen() sieht deshalb wie folgt aus:

Oh Klotilde, Du allein sollst und musst die Meine sein
Oh Klotilde, Du allein sollst und musst die Meine
Oh Klotilde, Du allein sollst und musst die
...

Das aufgerufende Programm manipuliert nur die Kopie eines Speicherplatzes des aurufenden Programms. Die Funktion einWortWeniger(Text) ändert zum Beispiel nur eine Kopie des Texts der Subroutine WortFürWortLöschen(). Die ursprüngliche Variable Text bleibt erhalten. Die Ausgabe von WortFürWortLöschen() wäre deshalb ...

Oh Klotilde, Du allein sollst und musst die Meine sein
Oh Klotilde, Du allein sollst und musst die Meine sein
...

Die Übergabe einer Adresse (call by reference) sollte nur dann gewählt werden, wenn der Entwickler sicher ist, dass die übergebene Variable des aufrufenden Programms geändert werden darf. Call by reference ist allerdings effizienter, weil keine Kopie erstellt werden muss. Es ist deshalb in den meisten Programmiersprachen die Voreinstellung. Wenn ein Argument als Kopie übergeben werden soll, muss es in der Vereinbarung des empfangenden Unterprogramms mit ByVal eingeleitet werden. Die folgende Abbildung veranschaulicht die Übergabe eines Arguments grafisch:

Argumentübergabe


Die folgende Tabelle bewertet die beiden Aufrufarten zusammenfassend:

By Reference

By Value

Syntax (Voreinstellung) ByVal
Übergabe Adresse Kopie
Speichereffizienz + -
Laufzeiteffizienz + -
Sicherheit - (Aufrufumgebung beeinflusst) + (Aufrufumgebung bleibt unbeeinflusst)